//creates line object
sCanvas.fn.line = function() {
	if (arguments.length !== 1 && arguments.length !== 2) {
		throw new Error("Wrong arguments was passed to line().");
	}
	
	var attrs,
		obj = new CanvasLine(this);
	
		if (arguments.length === 1) {
			attrs = arguments[0];
		} else {
			attrs = {
				x: arguments[0],
				y: arguments[1]
			};
		}

	obj.attr({
		fill: null,
		stroke: "black"
	});

	obj.attr(attrs);

	this.register(obj);
	this.autorepaint();
	return obj;
};



var CanvasLine = function(sc) {
	this.init(sc);
	this.initAttrs();
	
	this.segments = [ ];
	
	return this;
};

CanvasLine.prototype = new sCanvasObject();

CanvasLine.prototype.createFillPath = function(cx) {
	this.createStrokePath(cx);
};

CanvasLine.prototype.createStrokePath = function(cx) {
	//modificators ensures that line will not be blurred
	var modX = (this.attrs.lineWidth) % 2 === 1 ? 0.5 : 0;
	var modY = (this.attrs.lineWidth) % 2 === 1 ? 0.5 : 0;
	
	var i;
	
	cx.save();
	cx.translate(this.attrs.x + modX, this.attrs.y + modY);
	cx.rotate(this.attrs.rotation);
	cx.beginPath();
	
	cx.moveTo(
		-this.origin.x,
		-this.origin.y
	);
		
	for (i = 0; i < this.segments.length; i++) {
		this.segments[i].createPath(cx);
	}
	
	cx.restore();
};

CanvasLine.prototype.createPointInPath = function(cx) {
	this.createFillPath(cx);
};

CanvasLine.prototype.box = function() {};

//stores line segments
CanvasLine.prototype.segments = null;

//adds newly created straight line segment to line
CanvasLine.prototype.addLine = function(x, y) {
	this.segments.push(new CanvasStraightSegment(
		this,
		x - this.attrs.x,
		y - this.attrs.y
	));
	
	this.sc.autorepaint();
	
	return this;
};

//adds newly created quadratic Bezier curve segment to line
CanvasLine.prototype.addQuadratic = function(x, y, cpx, cpy) {
	this.segments.push(new CanvasQuadraticSegment(
		this,
		x - this.attrs.x,
		y - this.attrs.y,
		cpx - this.attrs.x,
		cpy - this.attrs.y
	));
	
	this.sc.autorepaint();
	
	return this;
};

//adds newly created cubic Bezier curve segment to line
CanvasLine.prototype.addCubic = function(x, y, cp1x, cp1y, cp2x, cp2y) {
	this.segments.push(new CanvasCubicSegment(
		this,
		x - this.attrs.x,
		y - this.attrs.y,
		cp1x - this.attrs.x,
		cp1y - this.attrs.y,
		cp2x - this.attrs.x,
		cp2y - this.attrs.y
	));
	
	this.sc.autorepaint();
	
	return this;
};



//parent of all line segments
var CanvasLineSegment = function() {
	return this;
};

//stores reference to line in which segment is placed
CanvasLineSegment.prototype.line = null;

//draws line segment
CanvasLineSegment.prototype.createPath = function(cx) {
	throw new Error("Method CanvasLineSegment.createPath() should be overriden!");
};



//straight line segment
var CanvasStraightSegment = function(line, x, y) {
	this.line = line;
	this.end = {
		x: x,
		y: y
	};
};

CanvasStraightSegment.prototype = new CanvasLineSegment();

CanvasStraightSegment.prototype.createPath = function(cx) {
	cx.lineTo(
		this.end.x - this.line.origin.x,
		this.end.y - this.line.origin.y
	);
};

//end point
CanvasStraightSegment.prototype.end = null;



//quadratic Bezier curve segment
var CanvasQuadraticSegment = function(line, x, y, cpx, cpy) {
	this.line = line;
	this.end = {
		x: x,
		y: y
	};
	this.cp = {
		x: cpx,
		y: cpy
	};
};

CanvasQuadraticSegment.prototype = new CanvasLineSegment();

//end point
CanvasQuadraticSegment.prototype.end = null;

//control point
CanvasQuadraticSegment.prototype.cp = null;

CanvasQuadraticSegment.prototype.createPath = function(cx) {
	cx.quadraticCurveTo(
		this.cp.x - this.line.origin.x,
		this.cp.y - this.line.origin.y,
		this.end.x - this.line.origin.x,
		this.end.y - this.line.origin.y
	);
};



//quadratic Bezier curve segment
var CanvasCubicSegment = function(line, x, y, cp1x, cp1y, cp2x, cp2y) {
	this.line = line;
	this.end = {
		x: x,
		y: y
	};
	this.cp1 = {
		x: cp1x,
		y: cp1y
	};
	this.cp2 = {
		x: cp2x,
		y: cp2y
	};
};

CanvasCubicSegment.prototype = new CanvasLineSegment();

CanvasCubicSegment.prototype.createPath = function(cx) {
	cx.bezierCurveTo(
		this.cp1.x - this.line.origin.x,
		this.cp1.y - this.line.origin.y,
		this.cp2.x - this.line.origin.x,
		this.cp2.y - this.line.origin.y,
		this.end.x - this.line.origin.x,
		this.end.y - this.line.origin.y
	);
};

//end point
CanvasCubicSegment.prototype.end = null;

//first control point
CanvasCubicSegment.prototype.cp1 = null;

//second control point
CanvasCubicSegment.prototype.cp2 = null;